home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / posix-date < prev    next >
Encoding:
Text File  |  1992-03-01  |  20.7 KB  |  858 lines

  1. Newsgroups: comp.sources.unix
  2. From: arnold@skeeve.ATL.GA.US (Arnold Robbins)
  3. Subject: v25i149: posix-date - implementation of posix date(1) and strftime(3)
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: arnold@skeeve.ATL.GA.US (Arnold Robbins)
  8. Posting-Number: Volume 25, Issue 149
  9. Archive-Name: posix-date
  10.  
  11. This package implements the Posix 1003.2 Draft 11 date command, as a
  12. wrapper around an extended version of the ANSI strftime(3) library
  13. routine.  Everything in it is public domain.
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of shell archive."
  22. # Contents:  README Makefile date.1 date.c strftime.3 strftime.c
  23. # Wrapped by vixie@cognition.pa.dec.com on Sun Mar  1 20:21:02 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'README' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'README'\"
  27. else
  28. echo shar: Extracting \"'README'\" \(457 characters\)
  29. sed "s/^X//" >'README' <<'END_OF_FILE'
  30. Sun Mar  1 06:53:51 EST 1992
  31. X
  32. This package implements the Posix 1003.2 Draft 11 date command, as a
  33. wrapper around an extended version of the ANSI strftime(3) library
  34. routine.  Everything in it is public domain.
  35. X
  36. Arnold Robbins -- The Basement Computer        | Laundry increases
  37. Internet: arnold@skeeve.ATL.GA.US        | exponentially in the
  38. UUCP:    { gatech, emory }!skeeve!arnold        | number of children.
  39. Bitnet:    Forget it. Get on a real network.    |    -- Miriam Robbins
  40. END_OF_FILE
  41. if test 457 -ne `wc -c <'README'`; then
  42.     echo shar: \"'README'\" unpacked with wrong size!
  43. fi
  44. # end of 'README'
  45. fi
  46. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  47.   echo shar: Will not clobber existing file \"'Makefile'\"
  48. else
  49. echo shar: Extracting \"'Makefile'\" \(195 characters\)
  50. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  51. X# Makefile for PD date and strftime
  52. X
  53. SRCS= date.c strftime.c
  54. OBJS= date.o strftime.o
  55. DOCS= date.1 strftime.3
  56. X
  57. date: $(OBJS)
  58. X    $(CC) $(CFLAGS) $(OBJS) -o $@
  59. X
  60. date.o: date.c
  61. X
  62. strftime.o: strftime.c
  63. END_OF_FILE
  64. if test 195 -ne `wc -c <'Makefile'`; then
  65.     echo shar: \"'Makefile'\" unpacked with wrong size!
  66. fi
  67. # end of 'Makefile'
  68. fi
  69. if test -f 'date.1' -a "${1}" != "-c" ; then 
  70.   echo shar: Will not clobber existing file \"'date.1'\"
  71. else
  72. echo shar: Extracting \"'date.1'\" \(1342 characters\)
  73. sed "s/^X//" >'date.1' <<'END_OF_FILE'
  74. X.TH DATE 1
  75. X.SH NAME
  76. date \- write the date and time
  77. X.SH SYNOPSIS
  78. X.B date
  79. X[
  80. X.B \-u
  81. X] [
  82. X.RI + format
  83. X]
  84. X.SH DESCRIPTION
  85. X.I Date
  86. writes the current date and time to the standard output.
  87. It is intended to be compliant with draft 11 of the Posix
  88. X1003.2 Command Language and Utilities standard.
  89. Therefore, it is purposely
  90. X.I not
  91. usable by the super-user for setting the system time.
  92. X.LP
  93. X.I Date
  94. accepts one option:
  95. X.TP
  96. X.B \-u
  97. Perform operations as if the
  98. X.B TZ
  99. environment variable was set to
  100. X.BR GMT0 .
  101. X.LP
  102. If an argument to 
  103. X.I date
  104. is given that begins with a ``+'',
  105. then the output is controlled by the contents of the rest of
  106. the string.  Normal text is output unmodified, while field descriptors
  107. in the format string are substituted for.
  108. X.LP
  109. The
  110. X.I date
  111. program is essentially a wrapper around
  112. X.IR strftime (3);
  113. see there for a description of the available formatting options.
  114. X.LP
  115. If no format string is given, or if it does not begin with a ``+'',
  116. then the default format of \fB"%a %b %e %H:%M:%S %Z %Y"\fR will
  117. be used.  This produces the traditional style of output, such as
  118. X``Sun Mar 17 10:32:47 EST 1991''.
  119. X.SH SEE ALSO
  120. time(2), strftime(3), localtime(3)
  121. X.SH BUGS
  122. This version only works for the POSIX locale.
  123. X.SH AUTHOR
  124. X.nf
  125. Arnold Robbins
  126. X.sp
  127. INTERNET: arnold@skeeve.atl.ga.us
  128. UUCP:     emory!skeeve!arnold
  129. Phone:    +1 404 248 9324
  130. X.fi
  131. END_OF_FILE
  132. if test 1342 -ne `wc -c <'date.1'`; then
  133.     echo shar: \"'date.1'\" unpacked with wrong size!
  134. fi
  135. # end of 'date.1'
  136. fi
  137. if test -f 'date.c' -a "${1}" != "-c" ; then 
  138.   echo shar: Will not clobber existing file \"'date.c'\"
  139. else
  140. echo shar: Extracting \"'date.c'\" \(1044 characters\)
  141. sed "s/^X//" >'date.c' <<'END_OF_FILE'
  142. X/*
  143. X * date.c
  144. X *
  145. X * Public domain implementation of Posix 1003.2 Draft 11
  146. X * date command.  Lets strftime() do the dirty work.
  147. X */
  148. X
  149. X#include <stdio.h>
  150. X#include <sys/types.h>
  151. X#include <time.h>
  152. X
  153. extern char *malloc();
  154. extern size_t strftime();
  155. extern int getopt();
  156. extern int optind;
  157. X
  158. int
  159. main(argc, argv)
  160. int argc;
  161. char **argv;
  162. X{
  163. X    time_t clock;
  164. X    struct tm *now;
  165. X    int c, size, ret;
  166. X    char *defhow = "%a %b %e %H:%M:%S %Z %Y";
  167. X    char *howto = defhow;
  168. X    char *buf;
  169. X
  170. X    while ((c = getopt(argc, argv, "u")) != -1)
  171. X        switch (c) {
  172. X        case 'u':
  173. X            putenv("TZ=GMT0");
  174. X            break;
  175. X        default:
  176. X            fprintf(stderr, "usage: %s [-u] [+format_str]\n",
  177. X                argv[0]);
  178. X            exit(1);
  179. X        }
  180. X
  181. X    time(& clock);
  182. X    now = localtime(& clock);
  183. X
  184. X    if (optind < argc && argv[optind][0] == '+')
  185. X        howto = & argv[optind][1];
  186. X
  187. X    size = strlen(howto) * 10;
  188. X    if ((buf = malloc(size)) == NULL) {
  189. X        perror("not enough memory");
  190. X        exit(1);
  191. X    }
  192. X
  193. X    ret = strftime(buf, size, howto, now);
  194. X    if (ret != 0)
  195. X        printf("%s\n", buf);
  196. X    else {
  197. X        fprintf(stderr, "conversion failed\n");
  198. X        exit(1);
  199. X    }
  200. X    
  201. X    exit(0);
  202. X}
  203. END_OF_FILE
  204. if test 1044 -ne `wc -c <'date.c'`; then
  205.     echo shar: \"'date.c'\" unpacked with wrong size!
  206. fi
  207. # end of 'date.c'
  208. fi
  209. if test -f 'strftime.3' -a "${1}" != "-c" ; then 
  210.   echo shar: Will not clobber existing file \"'strftime.3'\"
  211. else
  212. echo shar: Extracting \"'strftime.3'\" \(5887 characters\)
  213. sed "s/^X//" >'strftime.3' <<'END_OF_FILE'
  214. X.TH STRFTIME 3
  215. X.SH NAME
  216. strftime \- generate formatted time information
  217. X.SH SYNOPSIS
  218. X.ft B
  219. X.nf
  220. X#include <sys/types.h>
  221. X#include <time.h>
  222. X.sp
  223. size_t strftime(char *s, size_t maxsize, const char *format,
  224. X    const struct tm *timeptr);
  225. X.SH DESCRIPTION
  226. The following description is transcribed verbatim from the December 7, 1988
  227. draft standard for ANSI C.
  228. This draft is essentially identical in technical content
  229. to the final version of the standard.
  230. X.LP
  231. The
  232. X.B strftime
  233. function places characters into the array pointed to by
  234. X.B s
  235. as controlled by the string pointed to by
  236. X.BR format .
  237. The format shall be a multibyte character sequence, beginning and ending in
  238. its initial shift state.
  239. The
  240. X.B format
  241. string consists of zero or more conversion specifiers and ordinary
  242. multibyte characters.  A conversion specifier consists of a
  243. X.B %
  244. character followed by a character that determines the behavior of the
  245. conversion specifier.
  246. All ordinary multibyte characters (including the terminating null
  247. character) are copied unchanged into the array.
  248. If copying takes place between objects that overlap the behavior is undefined.
  249. No more than
  250. X.B maxsize
  251. characters are placed into the array.
  252. XEach conversion specifier is replaced by appropriate characters as described
  253. in the following list.
  254. The appropriate characters are determined by the
  255. X.B LC_TIME
  256. category of the current locale and by the values contained in the
  257. structure pointed to by
  258. X.BR timeptr .
  259. X.TP
  260. X.B %a
  261. is replaced by the locale's abbreviated weekday name.
  262. X.TP
  263. X.B %A
  264. is replaced by the locale's full weekday name.
  265. X.TP
  266. X.B %b
  267. is replaced by the locale's abbreviated month name.
  268. X.TP
  269. X.B %B
  270. is replaced by the locale's full month name.
  271. X.TP
  272. X.B %c
  273. is replaced by the locale's appropriate date and time representation.
  274. X.TP
  275. X.B %d
  276. is replaced by the day of the month as a decimal number
  277. X.RB ( 01 - 31 ).
  278. X.TP
  279. X.B %H
  280. is replaced by the hour (24-hour clock) as a decimal number
  281. X.RB ( 00 - 23 ).
  282. X.TP
  283. X.B %I
  284. is replaced by the hour (12-hour clock) as a decimal number
  285. X.RB ( 01 - 12 ).
  286. X.TP
  287. X.B %j
  288. is replaced by the day of the year as a decimal number
  289. X.RB ( 001 - 366 ).
  290. X.TP
  291. X.B %m
  292. is replaced by the month as a decimal number
  293. X.RB ( 01 - 12 ).
  294. X.TP
  295. X.B %M
  296. is replaced by the minute as a decimal number
  297. X.RB ( 00 - 59 ).
  298. X.TP
  299. X.B %p
  300. is replaced by the locale's equivalent of the AM/PM designations associated
  301. with a 12-hour clock.
  302. X.TP
  303. X.B %S
  304. is replaced by the second as a decimal number
  305. X.RB ( 00 - 61 ).
  306. X.TP
  307. X.B %U
  308. is replaced by the week number of the year (the first Sunday as the first
  309. day of week 1) as a decimal number
  310. X.RB ( 00 - 53 ).
  311. X.TP
  312. X.B %w
  313. is replaced by the weekday as a decimal number
  314. X.RB [ "0 " (Sunday)- 6 ].
  315. X.TP
  316. X.B %W
  317. is replaced by the week number of the year (the first Monday as the first
  318. day of week 1) as a decimal number
  319. X.RB ( 00 - 53 ).
  320. X.TP
  321. X.B %x
  322. is replaced by the locale's appropriate date representation.
  323. X.TP
  324. X.B %X
  325. is replaced by the locale's appropriate time representation.
  326. X.TP
  327. X.B %y
  328. is replaced by the year without century as a decimal number
  329. X.RB ( 00 - 99 ).
  330. X.TP
  331. X.B %Y
  332. is replaced by the year with century as a decimal number.
  333. X.TP
  334. X.B %Z
  335. is replaced by the time zone name or abbreviation, or by no characters if
  336. no time zone is determinable.
  337. X.TP
  338. X.B %%
  339. is replaced by
  340. X.BR % .
  341. X.LP
  342. If a conversion specifier is not one of the above, the behavior is
  343. undefined.
  344. X.SH RETURNS
  345. If the total number of resulting characters including the terminating null
  346. character is not more than
  347. X.BR maxsize ,
  348. the
  349. X.B strftime
  350. function returns the number of characters placed into the array pointed to
  351. by
  352. X.B s
  353. not including the terminating null character.
  354. Otherwise, zero is returned and the contents of the array are indeterminate.
  355. X.SH NON-ANSI EXTENSIONS
  356. If
  357. X.B SYSV_EXT
  358. is defined when the routine is compiled, then the following additional
  359. conversions will be available.
  360. These are borrowed from the System V
  361. X.IR cftime (3)
  362. and
  363. X.IR ascftime (3)
  364. routines.
  365. X.TP
  366. X.B %D
  367. is equivalent to specifying
  368. X.BR %m/%d/%y .
  369. X.TP
  370. X.B %e
  371. is replaced by the day of the month,
  372. padded with a blank if it is only one digit.
  373. X.TP
  374. X.B %h
  375. is equivalent to
  376. X.BR %b ,
  377. above.
  378. X.TP
  379. X.B %n
  380. is replaced with a newline character (\s-1ASCII LF\s+1).
  381. X.TP
  382. X.B %r
  383. is equivalent to specifying
  384. X.BR "%I:%M:%S %p" .
  385. X.TP
  386. X.B %R
  387. is equivalent to specifying
  388. X.BR %H:%M .
  389. X.TP
  390. X.B %T
  391. is equivalent to specifying
  392. X.BR %H:%M:%S .
  393. X.TP
  394. X.B %t
  395. is replaced with a \s-1TAB\s+1 character.
  396. X.SH POSIX 1003.2 EXTENSIONS
  397. If
  398. X.B POSIX2_DATE
  399. is defined, then all of the conversions available with
  400. X.B SYSV_EXT
  401. are available, as well as the
  402. following additional conversions:
  403. X.TP
  404. X.B %C
  405. The century, as a number between 00 and 99.
  406. X.LP
  407. In additon, the alternate representations
  408. X.BR %Ec ,
  409. X.BR %EC ,
  410. X.BR %Ex ,
  411. X.BR %Ey ,
  412. X.BR %EY ,
  413. X.BR %Od ,
  414. X.BR %Oe ,
  415. X.BR %OH ,
  416. X.BR %OI ,
  417. X.BR %Om ,
  418. X.BR %OM ,
  419. X.BR %OS ,
  420. X.BR %OU ,
  421. X.BR %Ow ,
  422. X.BR %OW ,
  423. and
  424. X.B %Oy
  425. are recognized, but their normal representations are used.
  426. X.SH VMS EXTENSIONS
  427. If
  428. X.B VMS_EXT
  429. is defined, then the following additional conversion is available:
  430. X.TP
  431. X.B %V
  432. The date in VMS format (e.g. 20-JUN-1991).
  433. X.SH SEE ALSO
  434. time(2), ctime(3), localtime(3)
  435. X.SH BUGS
  436. This version does not handle multibyte characters or pay attention to the
  437. setting of the
  438. X.B LC_TIME
  439. environment variable.
  440. X.LP
  441. It is not clear what is ``appropriate'' for the C locale; the values
  442. returned are a best guess on the author's part.
  443. X.SH CAVEATS
  444. This implementation calls
  445. X.IR tzset (3)
  446. exactly once.  If the
  447. X.B TZ
  448. environment variable is changed after
  449. X.B strftime
  450. has been called, then
  451. X.IR tzset (3)
  452. must be called again, explicitly, in order for the
  453. correct timezone information to be available.
  454. X.SH AUTHOR
  455. X.nf
  456. Arnold Robbins
  457. X.sp
  458. INTERNET: arnold@skeeve.atl.ga.us
  459. UUCP:     emory!skeeve!arnold
  460. Phone:    +1 404 248 9324
  461. X.fi
  462. X.SH ACKNOWLEDGEMENTS
  463. Thanks to Geoff Clare <gwc@root.co.uk> for helping debug earlier
  464. versions of this routine.
  465. Additional thanks to Arthur David Olsen <ado@elsie.nci.nih.gov>
  466. for some code improvements.
  467. END_OF_FILE
  468. if test 5887 -ne `wc -c <'strftime.3'`; then
  469.     echo shar: \"'strftime.3'\" unpacked with wrong size!
  470. fi
  471. # end of 'strftime.3'
  472. fi
  473. if test -f 'strftime.c' -a "${1}" != "-c" ; then 
  474.   echo shar: Will not clobber existing file \"'strftime.c'\"
  475. else
  476. echo shar: Extracting \"'strftime.c'\" \(8508 characters\)
  477. sed "s/^X//" >'strftime.c' <<'END_OF_FILE'
  478. X/*
  479. X * strftime.c
  480. X *
  481. X * Public-domain relatively quick-and-dirty implemenation of
  482. X * ANSI library routine for System V Unix systems.
  483. X *
  484. X * It's written in old-style C for maximal portability.
  485. X * However, since I'm used to prototypes, I've included them too.
  486. X *
  487. X * If you want stuff in the System V ascftime routine, add the SYSV_EXT define.
  488. X * For stuff needed to implement the P1003.2 date command, add POSIX2_DATE.
  489. X *
  490. X * The code for %c, %x, and %X is my best guess as to what's "appropriate".
  491. X * This version ignores LOCALE information.
  492. X * It also doesn't worry about multi-byte characters.
  493. X * So there.
  494. X *
  495. X * Arnold Robbins
  496. X * January, February, March, 1991
  497. X *
  498. X * Fixes from ado@elsie.nci.nih.gov
  499. X * February 1991
  500. X */
  501. X
  502. X#include <stdio.h>
  503. X#include <ctype.h>
  504. X#include <string.h>
  505. X#include <time.h>
  506. X#include <sys/types.h>
  507. X
  508. X#ifndef __STDC__
  509. X#define const    /**/
  510. X#endif
  511. X
  512. X#ifndef __STDC__
  513. extern void tzset();
  514. extern char *strchr();
  515. static int weeknumber();
  516. X#else
  517. extern void tzset(void);
  518. extern char *strchr(const char *str, int ch);
  519. static int weeknumber(const struct tm *timeptr, int firstweekday);
  520. X#endif
  521. X
  522. extern char *tzname[2];
  523. extern int daylight;
  524. X
  525. X#define SYSV_EXT    1    /* stuff in System V ascftime routine */
  526. X#define POSIX2_DATE    1    /* stuff in Posix 1003.2 date command */
  527. X#define VMS_EXT        1    /* include %V for VMS date format */
  528. X
  529. X#if defined(POSIX2_DATE) && ! defined(SYSV_EXT)
  530. X#define SYSV_EXT    1
  531. X#endif
  532. X
  533. X/* strftime --- produce formatted time */
  534. X
  535. X#ifndef __STDC__
  536. size_t
  537. strftime(s, maxsize, format, timeptr)
  538. char *s;
  539. size_t maxsize;
  540. const char *format;
  541. const struct tm *timeptr;
  542. X#else
  543. size_t
  544. strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
  545. X#endif
  546. X{
  547. X    char *endp = s + maxsize;
  548. X    char *start = s;
  549. X    char tbuf[100];
  550. X    int i;
  551. X    static short first = 1;
  552. X
  553. X    /* various tables, useful in North America */
  554. X    static char *days_a[] = {
  555. X        "Sun", "Mon", "Tue", "Wed",
  556. X        "Thu", "Fri", "Sat",
  557. X    };
  558. X    static char *days_l[] = {
  559. X        "Sunday", "Monday", "Tuesday", "Wednesday",
  560. X        "Thursday", "Friday", "Saturday",
  561. X    };
  562. X    static char *months_a[] = {
  563. X        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  564. X        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  565. X    };
  566. X    static char *months_l[] = {
  567. X        "January", "February", "March", "April",
  568. X        "May", "June", "July", "August", "September",
  569. X        "October", "November", "December",
  570. X    };
  571. X    static char *ampm[] = { "AM", "PM", };
  572. X
  573. X    if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
  574. X        return 0;
  575. X
  576. X    if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize)
  577. X        return 0;
  578. X
  579. X    if (first) {
  580. X        tzset();
  581. X        first = 0;
  582. X    }
  583. X
  584. X    for (; *format && s < endp - 1; format++) {
  585. X        tbuf[0] = '\0';
  586. X        if (*format != '%') {
  587. X            *s++ = *format;
  588. X            continue;
  589. X        }
  590. X    again:
  591. X        switch (*++format) {
  592. X        case '\0':
  593. X            *s++ = '%';
  594. X            goto out;
  595. X
  596. X        case '%':
  597. X            *s++ = '%';
  598. X            continue;
  599. X
  600. X        case 'a':    /* abbreviated weekday name */
  601. X            if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
  602. X                strcpy(tbuf, "?");
  603. X            else
  604. X                strcpy(tbuf, days_a[timeptr->tm_wday]);
  605. X            break;
  606. X
  607. X        case 'A':    /* full weekday name */
  608. X            if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
  609. X                strcpy(tbuf, "?");
  610. X            else
  611. X                strcpy(tbuf, days_l[timeptr->tm_wday]);
  612. X            break;
  613. X
  614. X#ifdef SYSV_EXT
  615. X        case 'h':    /* abbreviated month name */
  616. X#endif
  617. X        case 'b':    /* abbreviated month name */
  618. X            if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
  619. X                strcpy(tbuf, "?");
  620. X            else
  621. X                strcpy(tbuf, months_a[timeptr->tm_mon]);
  622. X            break;
  623. X
  624. X        case 'B':    /* full month name */
  625. X            if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
  626. X                strcpy(tbuf, "?");
  627. X            else
  628. X                strcpy(tbuf, months_l[timeptr->tm_mon]);
  629. X            break;
  630. X
  631. X        case 'c':    /* appropriate date and time representation */
  632. X            sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
  633. X                days_a[timeptr->tm_wday],
  634. X                months_a[timeptr->tm_mon],
  635. X                timeptr->tm_mday,
  636. X                timeptr->tm_hour,
  637. X                timeptr->tm_min,
  638. X                timeptr->tm_sec,
  639. X                timeptr->tm_year + 1900);
  640. X            break;
  641. X
  642. X        case 'd':    /* day of the month, 01 - 31 */
  643. X            sprintf(tbuf, "%02d", timeptr->tm_mday);
  644. X            break;
  645. X
  646. X        case 'H':    /* hour, 24-hour clock, 00 - 23 */
  647. X            sprintf(tbuf, "%02d", timeptr->tm_hour);
  648. X            break;
  649. X
  650. X        case 'I':    /* hour, 12-hour clock, 01 - 12 */
  651. X            i = timeptr->tm_hour;
  652. X            if (i == 0)
  653. X                i = 12;
  654. X            else if (i > 12)
  655. X                i -= 12;
  656. X            sprintf(tbuf, "%02d", i);
  657. X            break;
  658. X
  659. X        case 'j':    /* day of the year, 001 - 366 */
  660. X            sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
  661. X            break;
  662. X
  663. X        case 'm':    /* month, 01 - 12 */
  664. X            sprintf(tbuf, "%02d", timeptr->tm_mon + 1);
  665. X            break;
  666. X
  667. X        case 'M':    /* minute, 00 - 59 */
  668. X            sprintf(tbuf, "%02d", timeptr->tm_min);
  669. X            break;
  670. X
  671. X        case 'p':    /* am or pm based on 12-hour clock */
  672. X            if (timeptr->tm_hour < 12)
  673. X                strcpy(tbuf, ampm[0]);
  674. X            else
  675. X                strcpy(tbuf, ampm[1]);
  676. X            break;
  677. X
  678. X        case 'S':    /* second, 00 - 61 */
  679. X            sprintf(tbuf, "%02d", timeptr->tm_sec);
  680. X            break;
  681. X
  682. X        case 'U':    /* week of year, Sunday is first day of week */
  683. X            sprintf(tbuf, "%d", weeknumber(timeptr, 0));
  684. X            break;
  685. X
  686. X        case 'w':    /* weekday, Sunday == 0, 0 - 6 */
  687. X            sprintf(tbuf, "%d", timeptr->tm_wday);
  688. X            break;
  689. X
  690. X        case 'W':    /* week of year, Monday is first day of week */
  691. X            sprintf(tbuf, "%d", weeknumber(timeptr, 1));
  692. X            break;
  693. X
  694. X        case 'x':    /* appropriate date representation */
  695. X            sprintf(tbuf, "%s %s %2d %d",
  696. X                days_a[timeptr->tm_wday],
  697. X                months_a[timeptr->tm_mon],
  698. X                timeptr->tm_mday,
  699. X                timeptr->tm_year + 1900);
  700. X            break;
  701. X
  702. X        case 'X':    /* appropriate time representation */
  703. X            sprintf(tbuf, "%02d:%02d:%02d",
  704. X                timeptr->tm_hour,
  705. X                timeptr->tm_min,
  706. X                timeptr->tm_sec);
  707. X            break;
  708. X
  709. X        case 'y':    /* year without a century, 00 - 99 */
  710. X            i = timeptr->tm_year % 100;
  711. X            sprintf(tbuf, "%d", i);
  712. X            break;
  713. X
  714. X        case 'Y':    /* year with century */
  715. X            sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
  716. X            break;
  717. X
  718. X        case 'Z':    /* time zone name or abbrevation */
  719. X            i = 0;
  720. X            if (daylight && timeptr->tm_isdst)
  721. X                i = 1;
  722. X            strcpy(tbuf, tzname[i]);
  723. X            break;
  724. X
  725. X#ifdef SYSV_EXT
  726. X        case 'n':    /* same as \n */
  727. X            tbuf[0] = '\n';
  728. X            tbuf[1] = '\0';
  729. X            break;
  730. X
  731. X        case 't':    /* same as \t */
  732. X            tbuf[0] = '\t';
  733. X            tbuf[1] = '\0';
  734. X            break;
  735. X
  736. X        case 'D':    /* date as %m/%d/%y */
  737. X            strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
  738. X            break;
  739. X
  740. X        case 'e':    /* day of month, blank padded */
  741. X            sprintf(tbuf, "%2d", timeptr->tm_mday);
  742. X            break;
  743. X
  744. X        case 'r':    /* time as %I:%M:%S %p */
  745. X            strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);
  746. X            break;
  747. X
  748. X        case 'R':    /* time as %H:%M */
  749. X            strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
  750. X            break;
  751. X
  752. X        case 'T':    /* time as %H:%M:%S */
  753. X            strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
  754. X            break;
  755. X#endif
  756. X
  757. X
  758. X#ifdef VMS_EXT
  759. X        case 'V':    /* date as dd-bbb-YYYY */
  760. X            sprintf(tbuf, "%2d-%3.3s-%4d",
  761. X                timeptr->tm_mday,
  762. X                months_a[timeptr->tm_mon],
  763. X                timeptr->tm_year + 1900);
  764. X            for (i = 3; i < 6; i++)
  765. X                if (islower(tbuf[i]))
  766. X                    tbuf[i] = toupper(tbuf[i]);
  767. X            break;
  768. X#endif
  769. X
  770. X
  771. X#ifdef POSIX2_DATE
  772. X        case 'C':
  773. X            sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
  774. X            break;
  775. X
  776. X
  777. X        case 'E':
  778. X        case 'O':
  779. X            /* POSIX locale extensions, ignored for now */
  780. X            goto again;
  781. X#endif
  782. X        default:
  783. X            tbuf[0] = '%';
  784. X            tbuf[1] = *format;
  785. X            tbuf[2] = '\0';
  786. X            break;
  787. X        }
  788. X        i = strlen(tbuf);
  789. X        if (i)
  790. X            if (s + i < endp - 1) {
  791. X                strcpy(s, tbuf);
  792. X                s += i;
  793. X            } else
  794. X                return 0;
  795. X    }
  796. out:
  797. X    if (s < endp && *format == '\0') {
  798. X        *s = '\0';
  799. X        return (s - start);
  800. X    } else
  801. X        return 0;
  802. X}
  803. X
  804. X/* weeknumber --- figure how many weeks into the year */
  805. X
  806. X/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */
  807. X
  808. X#ifndef __STDC__
  809. static int
  810. weeknumber(timeptr, firstweekday)
  811. const struct tm *timeptr;
  812. int firstweekday;
  813. X#else
  814. static int
  815. weeknumber(const struct tm *timeptr, int firstweekday)
  816. X#endif
  817. X{
  818. X    if (firstweekday == 0)
  819. X        return (timeptr->tm_yday + 7 - timeptr->tm_wday) / 7;
  820. X    else
  821. X        return (timeptr->tm_yday + 7 -
  822. X            (timeptr->tm_wday ? (timeptr->tm_wday - 1) : 6)) / 7;
  823. X}
  824. X
  825. X#if 0
  826. X/* ADR --- I'm loathe to mess with ado's code ... */
  827. X
  828. Date:         Wed, 24 Apr 91 20:54:08 MDT
  829. XFrom: Michal Jaegermann <audfax!emory!vm.ucs.UAlberta.CA!NTOMCZAK>
  830. To: arnold@audiofax.com
  831. X
  832. Hi Arnold,
  833. in a process of fixing of strftime() in libraries on Atari ST I grabbed
  834. some pieces of code from your own strftime.  When doing that it came
  835. to mind that your weeknumber() function compiles a little bit nicer
  836. in the following form:
  837. X/*
  838. X * firstweekday is 0 if starting in Sunday, non-zero if in Monday
  839. X */
  840. X{
  841. X    return (timeptr->tm_yday - timeptr->tm_wday +
  842. X        (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
  843. X}
  844. How nicer it depends on a compiler, of course, but always a tiny bit.
  845. X
  846. X   Cheers,
  847. X   Michal
  848. X   ntomczak@vm.ucs.ualberta.ca
  849. X#endif
  850. END_OF_FILE
  851. if test 8508 -ne `wc -c <'strftime.c'`; then
  852.     echo shar: \"'strftime.c'\" unpacked with wrong size!
  853. fi
  854. # end of 'strftime.c'
  855. fi
  856. echo shar: End of shell archive.
  857. exit 0
  858.